home *** CD-ROM | disk | FTP | other *** search
- /*
- * PASSWD -- a program to change passwords
- *
- * This program will change a password, but will do so
- * only after the proposed password passes a series of tests.
- */
- #include "passwd.h"
-
- /*
- * globals
- */
- char runner[BUFSIZ]; /* who is running this program */
- char user[BUFSIZ]; /* name of user */
- char password[BUFSIZ]; /* new password */
- char oldpassword[BUFSIZ]; /* current password */
- struct passwd *pwinfo; /* associated password structure */
- char *progname = "passwd"; /* program name */
- char *pwdfile = DEFPWFILE; /* password file */
- char pwtest[BUFSIZ] = PWTESTFILE; /* password test file */
- int pwsig = PWSIGCHARS; /* number of significant chars in password */
- #ifdef lint
- int errno; /* system error number */
- int sys_nerr; /* number of system errors */
- char *sys_errlist[1]; /* descriptions of system errors */
- #endif
-
- /*
- * main routine
- */
- main(argc, argv)
- int argc;
- char **argv;
- {
- register int i; /* counter in a for loop */
- register char *cp; /* pointer to various things */
- char saltc[2]; /* the password's salt */
- char ermsg[BUFSIZ]; /* returned message from test routine */
- #ifdef CHFN
- int dogecos = 0; /* 1 to change user's finger info */
- #endif
- #ifdef GETUSERSHELL
- int doshell = 0; /* 1 to change user's shell */
- #endif
- #ifdef UID_TYPE
- UID_TYPE getuid(); /* return user's real UID */
- union {
- UID_TYPE tuid; /* uid as returned by system */
- int iuid; /* uid as integer */
- } uuid; /* uid as union */
- #define uidget uuid.iuid
- #define uidset uuid.tuid
- #else
- int uuid; /* uid as returned by system */
- #define uidget uuid
- #define uidset uuid
- #endif
-
- /*
- * don't produce core dumps
- */
- initsig();
- nocore();
- name_pwd(pwdfile);
-
- /*
- * walk the argument list and process the arguments
- */
- progname = argv[0];
- for(i = 1; i < argc; i++){
- if (strncmp(argv[i], "-t", 2) == 0){/* new test file */
- if (argv[i][2] == '\0')
- (void) strcpy(pwtest, argv[++i]);
- else
- (void) strcpy(pwtest, &argv[i][2]);
- }
- #ifndef NOSETPWFILE
- else if (strncmp(argv[i], "-F", 2) == 0){/* new password file */
- if (argv[i][2] == '\0')
- name_pwd(pwdfile = argv[++i]);
- else
- name_pwd(pwdfile = &argv[i][2]);
- }
- #endif
- #ifdef CHFN
- else if (strcmp(argv[i], "-f") == 0) /* change gecos */
- dogecos = 1;
- #endif
- #ifdef GETUSERSHELL
- else if (strcmp(argv[i], "-s") == 0) /* change shell */
- doshell = 1;
- #endif
- else if (*argv[i] == '-'){ /* bad option */
- SPRINTF(user, "%s: unknown option.", argv[i]);
- pwexit(user);
- }
- else if (user[0] != '\0') /* too many args */
- pwexit("one user at a time");
- else /* change user */
- (void) strcpy(user, argv[i]);
- }
-
- /*
- * figure out who is using the program
- */
- uidset = getuid();
- if ((pwinfo = mgpwuid(uidget)) == NULL)
- pwexit("you're not in the password file");
- else
- (void) strcpy(runner, pwinfo->pw_name);
-
- /*
- * if a user is named he/she/it better be the current one ...
- * grab the password information
- */
- if (user[0] != '\0'){
- /*
- * be sure the user exists
- */
- if ((pwinfo = mgpwnam(user)) == NULL){
- if (uidget == ROOTID)
- pwexit("no such user");
- else
- pwexit("only superuser can change another's password");
- exit(1);
- }
- if (uidget != ROOTID && pwinfo->pw_uid != uidget){
- pwexit("only superuser can change another's password");
- exit(1);
- }
- }
- else
- (void) strcpy(user, pwinfo->pw_name);
-
- #ifdef CHFN
- #ifdef GETUSERSHELL
- /*
- * you can only change one of these at a time
- */
- if (doshell && dogecos)
- pwexit("Only one of -f and -s allowed.");
- #endif
- /*
- * if to change user info, do so
- * you never return from this routine
- */
- if (dogecos)
- chfn(pwinfo);
- #endif
- #ifdef GETUSERSHELL
- /*
- * if to change user shell, do so
- * you never return from this routine
- */
- if (doshell)
- chsh(pwinfo);
- #endif
-
- /*
- * if an alternate test file is named
- * the ROOTID must be running this program
- */
- if (strcmp(PWTESTFILE, pwtest) != 0 && uidget != ROOTID){
- pwexit("only superuser can change the test file");
- exit(1);
- }
-
- /*
- * if logging, initialize
- */
- initlog();
-
- /*
- * attempt to verify
- */
- if (uidget != ROOTID && (cp = getpass("Current password: ")) == NULL)
- pwexit("EOF in password -- no change");
-
- /*
- * now do the verification
- */
- if (uidget != ROOTID){
- if (!check_age(pwinfo))
- pwexit("too soon to change password -- no change");
- {
- char *s;
-
- s = crypt(cp, pwinfo->pw_passwd);
- printf("crypt password is %s, string is %s, comp hash is %s\n",
- pwinfo->pw_passwd, cp, s);
- }
- if (strcmp(pwinfo->pw_passwd, crypt(cp, pwinfo->pw_passwd)) != 0)
- pwexit("password incorrect -- no change");
- (void) strcpy(oldpassword, cp);
- }
- else
- (void) strcpy(oldpassword, "xxxxxxxx");
-
- /*
- * verified -- set the salt and ask for new password
- */
- makesalt(saltc);
- if ((cp = getpass("New password: ")) == NULL)
- pwexit("EOF in password -- no change");
-
- /*
- * got it -- now the encrypted form into memory
- */
- (void) strcpy(password, cp);
-
- /*
- * ask for it again (to catch typos)
- */
- if ((cp = getpass("Repeat new password: ")) == NULL)
- pwexit("EOF in password -- no change");
-
- /*
- * verify it
- */
- if (strcmp(password, cp) != 0)
- pwexit("typographical error in new password -- no change");
-
- /*
- * now see if it's an invalid password
- */
- if (!verify(ermsg)){
- /*
- * nope -- reject it
- */
- LOG0(LG_RESULT, "password unchanged");
- if (ermsg[0] == '\0')
- pwexit("password invalid -- no change");
- pwexit(ermsg);
- }
-
- /*
- * valid -- update the record
- */
- LOG0(LG_RESULT, "password to be changed");
- pwinfo->pw_passwd = crypt(password, saltc);
- if (update_pwd(pwinfo) < 0){
- errno = pf_errno;
- if (pf_errno < sys_nerr){
- (void) sprintf(ermsg, "%s: %s",
- pwdfile, sys_errlist[pf_errno]);
- }
- else
- (void) sprintf(ermsg, "%s: unknown error #%d",
- pwdfile, pf_errno);
- LOG0(LG_SYSTEM, ermsg);
- pwexit(ermsg);
- }
-
- /*
- * clean up and exit
- */
- exit(0);
- }
-
- /*
- * generate a salt
- */
- makesalt(c)
- char c[2]; /* salt characters */
- {
- register long salt; /* used to compute a salt */
- register int i; /* counter in a for loop */
-
- /*
- * just mix a few things up for the salt ...
- * no rhyme or reason here
- */
- salt = (((long) time(TI_NULL))&0x3f) | (getpid() << 5);
-
- /*
- * use the bottom 12 bits and map them into the legal alphabet
- */
- for(i = 0; i < 2; i++){
- c[i] = (salt & 0x3f) + '.';
- if (c[i] > '9')
- c[i] += 7;
- if (c[i] > 'Z')
- c[i] += 6;
- salt >>= 6;
- }
- }
-
-